// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "WorldEntityPart.h"

class FWorldEntityManager;

/**
 * Base class of all the entities for Object-Json mapping.
 * Goal is to provide a JPA-fashion interface.
 */
class FWorldEntity : public FWorldEntityPart
{

public:

	using Ptr = std::shared_ptr<FWorldEntity>;
	using ConstPtr = std::shared_ptr<const FWorldEntity>;
	using WeakPtr = std::weak_ptr<FWorldEntity>;
	using ConstWeakPtr = std::weak_ptr<const FWorldEntity>;
	using Super = FWorldEntityPart;

	FWorldEntityProperty< std::int64_t >			ID;
	FWorldEntityProperty< std::string >				Geom;
	FWorldEntityProperty< std::int64_t >			WorldId;
	FWorldEntityProperty< int >						RevisionStart;
	FWorldEntityProperty< int >						RevisionEnd;
	FWorldEntityReference< FWorldEntity >			Referencer;
	FWorldEntityArrayReference< FWorldEntity >		Referencee;
	FWorldEntityProperty< std::string >				Class;
	FWorldEntityProperty< std::string >				XmlClob;
	FWorldEntityMapProperty< std::string >			Tags;

public:

	FWorldEntity();
	FWorldEntity(const json& j);
	~FWorldEntity() override;

	void ToXml(pugi::xml_node& elem) override;

	virtual json ToJson() const;

	WORLD_ENTITY_META_DECLARE(FWorldEntity)

protected:
	friend class FWorldEntityPropertyBase;	// Receiving changed messages.
	friend class FWorldEntityManager;		// Sending changed messages.

	enum class EntityState
	{
		New,
		Managed,
		Removed,
		Detached
	};

	virtual void EntityChanged();
	virtual void EntityFlushed();
	virtual void ChangeTo(EntityState state, FWorldEntityManager* em);
	virtual bool Is(EntityState state);
	virtual bool IsManagedBy(FWorldEntityManager* em);

	void Resolve(FWorldEntityReferencing& referencing) override;
	void PropertyChanged() override;

private:

	EntityState				_state;
	FWorldEntityManager*	_em;
	std::atomic<bool>		_dirty;
	pugi::xml_document		_xmldoc;

};
